package oop.ex3.search;

import java.util.Date;
import java.util.Iterator;
import java.util.TreeSet;


/**
 * 
 * @author danielshalev
 *
 * @param <B>
 * @param <M>
 */
public class MyDepthFirstSearch<B extends SearchBoardNode<M>, M extends SearchMove> implements DepthFirstSearch<B, M>{
	
	
	private B bestBoard;
	
	private int qualityUpperBound;
	
	private int bestQualityAchived;
	
	public void setBestBoard(B board){
		this.bestBoard=board;
		this.bestQualityAchived=board.getQuality();
	}
	
	public B getBestBoard(){
		if(bestQualityAchived<=0)
			return null;
		
		return bestBoard;
	}
	
	public void recursiveSearch(B currentBoard, int depthLeft, long timeLeft, long startTime){
		Date date=new Date();
		long currentTimeLeft=timeLeft-(date.getTime()-startTime);
		//check if the current board have the best quality so far
		if(currentBoard.getQuality()>bestQualityAchived){
			setBestBoard((B)currentBoard.getCopy());
		}
		//if there is no time left return best result so far
		if(!(currentTimeLeft>0)){
			return;
		}
		//check if the current board is the best solution
		if(currentBoard.isBestSolution() && currentBoard.getQuality()>0){
			return;
		}	
		
				
		Iterator<M> movesIterator=currentBoard.getMovesIterator();
		
		while(movesIterator.hasNext() && currentTimeLeft>0 ){
			M nextMove = movesIterator.next();
			currentBoard.doMove(nextMove);
			if(currentBoard.getQualityBound()>=bestQualityAchived && depthLeft>=0)
				recursiveSearch(currentBoard, depthLeft-1, timeLeft, startTime);
			currentBoard.undoMove(nextMove);
			
		}
		
			
		
	}
	
	@Override
	public B search(B startBoard, int maxDepth, long timeOut) {
		qualityUpperBound=startBoard.getQualityBound();
		bestQualityAchived=startBoard.getQuality();
		bestBoard=startBoard;
		Date date=new Date();
		long startTime=date.getTime();
		recursiveSearch(startBoard, maxDepth, timeOut, startTime);
		return getBestBoard();
	}

}
